package server.sisPensionesRecaudo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyPair;
import java.security.PublicKey;



/**
 * 
 * @author Mauricio Pradilla Hosie m.pradilla323@uniandes.edu.co
 * @author Martin Uribe Gutierrez m.uribe248@uniandes.edu.co
 * Infraestructura Computacional
 * Universidad de los Andes
 * Referencias de Algoritmos: 
 * http://www.java2s.com/Code/Java/Security/CatalogSecurity.htm
 * http://www.javafundu.com/2009/03/reading-bytes-from-any-inputstream.html
 * http://www.bouncycastle.org
 * Clase que representa el sistema de pensiones de recaudo, donde se llevan a cabo las transacciones bajo estrictos controles de seguridad
 * y un protocolo espec�fico
 */
public class SisPensionesRecaudo extends Thread  {
	
	
	/**
	 * Puerto Seguro por el cual se va a comunicarse con el servidor
	 */
	public final static int PUERTO_SEG = 1030;
	
	public final static int MIN = 20001;
	public final static int MAX = 20002;
	
	private int port;
	
	/**
	 * Modela el canal de recepci�n del servidor
	 */
	private ServerSocket serverSocket;
	
	/**
	 * Llave asim�trica
	 */
	private KeyPair asymKey;
	
	/**
	 * Llave p�ublica del cliente. Simula la llave que tendr�a el browser
	 */
	private PublicKey clientKey;
	
	/**
	 * Constructor de la Clase
	 * Se encarga de abrir el puerto para recibir conexiones y de crear un Thread para cada uno.
	 */
	private SisPensionesRecaudo(int newPort){	
		port = newPort;
	}
	
	/**
	 * Implementaci�n del m�todo run() la interfaz Thread. 
	 */
	public void run()
	{
		try {
			serverSocket = new ServerSocket(port);
			System.out.println("SisPensionesRecaudo Iniciado: "+port);
			cargarLlavesEntidadCertificadora(); 			
			while( true )
			{
				//Crea un nuevo thread por cada conexion.
				Socket nuevaConecion = serverSocket.accept();				
				Protocolo p = new Protocolo( nuevaConecion, asymKey, clientKey );
				p.start();
				
				System.out.println("Conexi�n recibida");
			}			
		} catch (IOException e) {
			
			e.printStackTrace();
		}

	}		
	
	/**
	 * M�todo encargado de cargar el archivo con las llaves p�blicas de los clientes y 
	 * las llaves privadas y p�blicas del servidor.
	 */
	private void cargarLlavesEntidadCertificadora() {		
		try {						
			
			FileInputStream nuevo = new FileInputStream("data/keys.obj");
			ObjectInputStream obj = new ObjectInputStream(nuevo);
			Object[] elementos = (Object[]) obj.readObject();
			//System.out.println(elementos);
			asymKey = (KeyPair) elementos[0];
			clientKey = (PublicKey) elementos[1];
			
			//System.out.println("la llave privada servidor es: "+asymKey.getPrivate());
			//System.out.println("la llave publica servidor es: "+asymKey.getPublic());
			//System.out.println("La llave p�blica del clientes es: "+ clientKey);			
			
		} catch (FileNotFoundException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}		
	}
	
	/**
	 * Metodo de inicio del servidor.
	 * @param args
	 */
	public static void main(String[] args) 
	{
		for (int i = MIN; i < MAX; i++) {
			SisPensionesRecaudo app = new SisPensionesRecaudo(i);
			app.start();
		}
	}
	
	public static void initialize() 
	{
		for (int i = MIN; i < MAX; i++) {
			SisPensionesRecaudo app = new SisPensionesRecaudo(i);
			app.start();
		}
	}	

}
